import asyncio
from aiohttp import ClientSession
from aiohttp_socks import ProxyConnector
from typing import Callable, Awaitable
from functools import partial, wraps

from loguru import logger

from capmonster_python import RecaptchaV2Task as CapmonsterRecaptcha
from python_anticaptcha import AnticaptchaClient, NoCaptchaTaskProxylessTask as AnticaptchaRecaptcha
from twocaptcha import TwoCaptcha

from web3.auto import w3

from random import choice
from re import findall

from sys import stdout
from concurrent.futures import ThreadPoolExecutor


EMAIL_HEADERS = {
        "requestverificationtoken": "CfDJ8AXQ6d5LLCdGlZgtgxMvXnffRzu6mjGpKijTrjU8SM30he2w6vsOIz0UsIXA0svp6zhNo9sHQs7L1sSoGHIdiUek5cwBg13l-_zH21rY3rs4XmbQhycnKuGIGaMwL3BxW3BxJX2_exIgHQRNTJEv2j8",
        "cookie": ".AspNetCore.Antiforgery.dXyz_uFU2og=CfDJ8AXQ6d5LLCdGlZgtgxMvXnc7V3B_a_YUGra_iYnioWQXkCs2xd5Z9gcoYyI0S_fmZADqd6hQlAhNrg3vt2v6m5H5Eu9cXQmUOgBXdo19Rh3i2zZj5nMabAdr3sP-f0VzjhVFzy4ClobRkRTmlqjY4zw; _ym_uid=1654525472841042508; _ym_isad=1; __cf_bm=GQ5MHyKpH8NavH7M6Mz6cRpPI5DkZsVPNd104Jx2sgI-1654525473-0-AaCalJ2vWVFra9K/JtZ/gAx+cyJxsnqE0KDgn363WS1Mj5u6FEPOJ0WspOx/I0bt5doELGKnMZtooTwA82zyKzAPx4XH/RzvQsH4afWGkCPCwdqYRScD7FTOEsrCjxBr6A==",
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36"
}


def get_proxy():
    return choice(proxy)


async def get_message(email: str):
    async with create_client(headers=EMAIL_HEADERS) as client:
        response = await client.post(
                "https://tempmailo.com",
                json={"mail": email})
        data = await response.json()
    for message in data:
        if message["from"] == "HELIX <no-reply@helixmetaverse.com>":
            return findall(r"VERIFY EMAIL \((.*)\)", message["text"])[0].strip()
    await asyncio.sleep(10)
    return await get_message(email)


def wrap(func):
    @wraps(func)
    async def run(*args, loop=None, executor=None, **kwargs):
        if loop is None:
            loop = asyncio.get_event_loop()
        pfunc = partial(func, *args, **kwargs)
        return await loop.run_in_executor(executor, pfunc)
    return run


async def create_email():
    async with create_client(headers=EMAIL_HEADERS) as client:
        response = await client.get(
                "https://tempmailo.com/changemail?_r=0.6008200314006913")
        data = await response.text()
    if data.strip() == "":
        raise Exception("Не удалось создать почту")
    return data.strip()


def create_wallet():
    account = w3.eth.account.create()
    return account.privateKey.hex(), account.address


@wrap
def solve_by_capmonster(api_key: str, site_url: str, site_key: str):
    client = CapmonsterRecaptcha(api_key)
    task = client.create_task(site_url, site_key)
    data = client.join_task_result(task)

    return data.get("gRecaptchaResponse")


@wrap
def solve_by_anticaptcha(api_key: str, site_url: str, site_key: str):
    client = AnticaptchaClient(api_key, language_pool="ru")
    task = AnticaptchaRecaptcha(site_url, site_key)
    task = client.createTask(task)
    task.join()

    return task.get_solution_response()


@wrap
def solve_by_twocaptcha(api_key: str, site_url: str, site_key: str):
    client = TwoCaptcha(api_key)
    return client.recaptcha(site_key, site_url).get("code")


solvers: list[Callable[[str, str, str], Awaitable[str]]] = [
    solve_by_twocaptcha,
    solve_by_anticaptcha,
    solve_by_capmonster
]


def create_client(**kwargs):
    proxy, connector = get_proxy(), None

    if proxy:
        connector = ProxyConnector.from_url(get_proxy())

    return ClientSession(connector=connector, **kwargs)


async def create_set_user_request(
        solver: Callable[[str, str], Awaitable[str]],
        r_id: str):
    try:
        logger.info("Решение капчи")
        code = await solver(
                "https://helixmetaverse.com",
                "6LeDrh0gAAAAAGeqVs6x1UCYwGELN6aQwV9ETN3Q")
        logger.info("Капча решена {}...", code[:4])

        logger.info("Создание почты")
        email = await create_email()

        logger.info("Почта создана {}", email)

        logger.info("Создание кошелька")
        private_address, address = create_wallet()
        logger.info("Кошелек создан {}", address)

        async with create_client(
                headers={
                    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36",
                    "accept": "*/*",
                    "accept-language": "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7",
                    "content-type": "text/plain;charset=UTF-8",
                    "sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"99\"",
                    "sec-ch-ua-mobile": "?0",
                    "sec-ch-ua-platform": "\"Windows\"",
                    "sec-fetch-dest": "empty",
                    "sec-fetch-mode": "cors",
                    "sec-fetch-site": "cross-site",
                    "Referer": "https://helixmetaverse.com/",
                    "Referrer-Policy": "strict-origin-when-cross-origin"}
                ) as client:
            logger.info("Отправка запроса на регистрацию")
            response = await client.post(
                    "https://mntixvzfga.execute-a"
                    "pi.us-east-1.amazonaws.com/setUser",
                    json={
                        "email": email,
                        "wallet": address,
                        "r_id": r_id,
                        "g-recaptcha-response": code
                    })
            data = await response.json()

            if "message" in data:
                raise Exception(
                        "Не удалось зарегистрировать аккаунт {}",
                        data["message"])

            logger.info("Верификация почты")
            message = await get_message(email)
            response = await client.get(message)
            secret = str(response.url).split("secret=")[-1]

            logger.info("Отправка верификационного запроса")
            response = await client.put(
                    "https://mntixvzfga.execute-a"
                    "pi.us-east-1.amazonaws.com/setUser",
                    json={
                        "uuid": data["uuid"],
                        "secret": secret
                    })
            data = await response.json()

            if "message" in data:
                raise Exception(
                        "Не уадлось зарегать акк {}",
                        data["message"])
        logger.success("{} - Аккаунт успешно зарегистрирован", data["uuid"])
        return email, address, private_address
    except Exception:
        logger.exception("ОШибка какая-то хуй знает")


async def main():
    solver_type, api_key = (
            input("Введите тип солвера капчи(1 - рукапча, 2"
                  " - антикапча, 3 - сапмонстер) -> "),
            input("Введите ключ от солвера -> "))
    solver = partial(solvers[int(solver_type) - 1], api_key)
    accounts_count = int(input("Введите кол-во аккаунтов, ско"
                               "лько вы хотите зарегистрировать -> "))
    r_id = input("Введите реф код -> ")

    logger.success("Запуск регистраций")
    tasks = [asyncio.create_task(create_set_user_request(solver, r_id))
             for _ in range(accounts_count)]

    accounts = await asyncio.gather(*tasks)

    for account in accounts:
        try:
            open("accounts.txt", "a+").write(
                    f"{account[0]}:{account[1]}:{account[2]}\n")
        except Exception:
            pass


try:
    proxy = open("proxies.txt").read().strip().split("\n")
except Exception:
    proxy = [None]

asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(main())
